<template>
  <div class="voice-comparison">
    <div class="page-header">
      <h1>声纹比对验证</h1>
      <p>通过声纹比对验证身份真实性</p>
    </div>

    <div class="comparison-container">
      <!-- 左侧：目标声纹选择 -->
      <div class="left-panel">
        <div class="target-selection">
          <h2>选择目标声纹</h2>
          <div class="voice-grid">
            <div 
              v-for="voice in voiceList" 
              :key="voice.id"
              class="voice-card"
              :class="{active: selectedVoice?.id === voice.id}"
              @click="selectVoice(voice)"
            >
              <div class="voice-avatar">
                <img :src="voice.avatar" :alt="voice.name">
              </div>
              <div class="voice-info">
                <h4>{{ voice.name }}</h4>
                <p>{{ voice.relationship }}</p>
                <div class="quality-indicator">
                  <div class="quality-bar">
                    <div class="quality-fill" :style="{width: voice.quality + '%'}"></div>
                  </div>
                  <span>{{ voice.quality }}%</span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 右侧：录音比对 -->
      <div class="right-panel">
        <div class="recording-section">
          <h2>录音比对</h2>
          
          <div class="recording-area">
            <div class="recording-visual">
              <div class="microphone-icon" :class="{active: isRecording}">
                <i class="fas fa-microphone"></i>
              </div>
              <div class="recording-status">
                <p v-if="!isRecording && !hasRecording">点击开始录音</p>
                <p v-if="isRecording">正在录音... {{ formatTime(recordingTime) }}</p>
                <p v-if="hasRecording && !isRecording">录音完成</p>
              </div>
            </div>

            <div class="recording-controls">
              <button 
                class="btn btn-record" 
                @click="toggleRecording"
                :disabled="!selectedVoice"
              >
                {{ isRecording ? '停止录音' : '开始录音' }}
              </button>
              <button 
                class="btn btn-play" 
                @click="playRecording"
                :disabled="!hasRecording"
              >
                播放录音
              </button>
              <button 
                class="btn btn-compare" 
                @click="startComparison"
                :disabled="!hasRecording || !selectedVoice"
              >
                开始比对
              </button>
            </div>
          </div>

          <!-- 比对结果 -->
          <div class="comparison-result" v-if="comparisonResult">
            <h3>比对结果</h3>
            <div class="result-display">
              <div class="similarity-score">
                <div class="score-circle" :class="getScoreClass(comparisonResult.similarity)">
                  <span class="score-value">{{ comparisonResult.similarity }}%</span>
                  <span class="score-label">相似度</span>
                </div>
              </div>
              <div class="result-info">
                <div class="info-item">
                  <label>匹配状态：</label>
                  <span class="status" :class="comparisonResult.status">
                    {{ comparisonResult.statusText }}
                  </span>
                </div>
                <div class="info-item">
                  <label>置信度：</label>
                  <span>{{ comparisonResult.confidence }}%</span>
                </div>
                <div class="info-item">
                  <label>检测时间：</label>
                  <span>{{ formatDateTime(comparisonResult.timestamp) }}</span>
                </div>
              </div>
            </div>
            <div class="result-actions">
              <button class="btn btn-primary" @click="saveResult">保存结果</button>
              <button class="btn btn-secondary" @click="resetComparison">重新比对</button>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 比对历史 -->
    <div class="history-section">
      <h2>比对历史</h2>
      <div class="history-table">
        <table>
          <thead>
            <tr>
              <th>时间</th>
              <th>目标声纹</th>
              <th>相似度</th>
              <th>状态</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="record in comparisonHistory" :key="record.id">
              <td>{{ formatDateTime(record.timestamp) }}</td>
              <td>{{ record.targetName }}</td>
              <td>
                <div class="similarity-bar">
                  <div class="similarity-fill" :style="{width: record.similarity + '%'}"></div>
                  <span>{{ record.similarity }}%</span>
                </div>
              </td>
              <td>
                <span class="status-badge" :class="record.status">
                  {{ record.statusText }}
                </span>
              </td>
              <td>
                <button class="btn btn-sm" @click="viewDetail(record)">查看</button>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

// 响应式数据
const selectedVoice = ref(null)
const isRecording = ref(false)
const hasRecording = ref(false)
const recordingTime = ref(0)
const comparisonResult = ref(null)

// 声纹列表
const voiceList = ref([
  {
    id: 1,
    name: '张三',
    relationship: '本人',
    avatar: '/api/placeholder/60/60',
    quality: 95
  },
  {
    id: 2,
    name: '李四',
    relationship: '家人',
    avatar: '/api/placeholder/60/60',
    quality: 92
  },
  {
    id: 3,
    name: '王五',
    relationship: '朋友',
    avatar: '/api/placeholder/60/60',
    quality: 88
  }
])

// 比对历史
const comparisonHistory = ref([
  {
    id: 1,
    timestamp: '2024-01-20 14:30:25',
    targetName: '张三',
    similarity: 94,
    status: 'match',
    statusText: '匹配'
  },
  {
    id: 2,
    timestamp: '2024-01-20 13:45:12',
    targetName: '李四',
    similarity: 89,
    status: 'match',
    statusText: '匹配'
  },
  {
    id: 3,
    timestamp: '2024-01-20 11:20:45',
    targetName: '王五',
    similarity: 65,
    status: 'possible',
    statusText: '可能匹配'
  }
])

// 方法
const selectVoice = (voice) => {
  selectedVoice.value = voice
  resetComparison()
}

const toggleRecording = () => {
  if (isRecording.value) {
    stopRecording()
  } else {
    startRecording()
  }
}

const startRecording = () => {
  isRecording.value = true
  recordingTime.value = 0
  
  const interval = setInterval(() => {
    recordingTime.value++
    if (recordingTime.value >= 60) {
      clearInterval(interval)
      stopRecording()
    }
  }, 1000)
}

const stopRecording = () => {
  isRecording.value = false
  hasRecording.value = true
}

const playRecording = () => {
  alert('播放录音（模拟）')
}

const startComparison = () => {
  if (!selectedVoice.value || !hasRecording.value) return
  
  // 模拟比对过程
  setTimeout(() => {
    const similarity = Math.floor(Math.random() * 40) + 60
    let status, statusText
    
    if (similarity >= 85) {
      status = 'match'
      statusText = '匹配'
    } else if (similarity >= 70) {
      status = 'possible'
      statusText = '可能匹配'
    } else {
      status = 'nomatch'
      statusText = '不匹配'
    }
    
    comparisonResult.value = {
      similarity,
      status,
      statusText,
      confidence: Math.floor(Math.random() * 20) + 80,
      timestamp: new Date().toISOString()
    }
  }, 2000)
}

const saveResult = () => {
  if (!comparisonResult.value) return
  
  const newRecord = {
    id: Date.now(),
    timestamp: comparisonResult.value.timestamp,
    targetName: selectedVoice.value.name,
    similarity: comparisonResult.value.similarity,
    status: comparisonResult.value.status,
    statusText: comparisonResult.value.statusText
  }
  
  comparisonHistory.value.unshift(newRecord)
  alert('结果已保存')
}

const resetComparison = () => {
  comparisonResult.value = null
  hasRecording.value = false
  recordingTime.value = 0
}

const viewDetail = (record) => {
  alert(`查看详情: ${record.id}`)
}

const formatTime = (seconds) => {
  const mins = Math.floor(seconds / 60)
  const secs = seconds % 60
  return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
}

const formatDateTime = (dateString) => {
  return new Date(dateString).toLocaleString()
}

const getScoreClass = (score) => {
  if (score >= 85) return 'high'
  if (score >= 70) return 'medium'
  return 'low'
}

onMounted(() => {
  // 初始化
})
</script>

<style scoped>
.voice-comparison {
  padding: 20px;
  max-width: 1600px;
  margin: 0 auto;
  background: #f5f7fa;
  min-height: 100vh;
}

/* 响应式设计 */
@media (max-width: 1600px) {
  .voice-comparison {
    width: 90%;
  }
}

@media (max-width: 1200px) {
  .voice-comparison {
    width: 95%;
  }
}

@media (max-width: 768px) {
  .voice-comparison {
    width: 100%;
    padding: 10px;
  }
}

.page-header {
  text-align: center;
  margin-bottom: 30px;
}

.page-header h1 {
  color: #1e3c72;
  margin-bottom: 10px;
}

.comparison-container {
  display: flex;
  gap: 30px;
  margin-bottom: 40px;
}

.left-panel, .right-panel {
  flex: 1;
  background: white;
  border-radius: 8px;
  padding: 25px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.target-selection h2, .recording-section h2 {
  color: #1e3c72;
  margin-bottom: 20px;
}

.voice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 15px;
}

.voice-card {
  border: 2px solid #eee;
  border-radius: 8px;
  padding: 15px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.voice-card:hover {
  border-color: #1e3c72;
}

.voice-card.active {
  border-color: #1e3c72;
  background: #f8f9ff;
}

.voice-avatar {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  overflow: hidden;
  margin: 0 auto 10px;
}

.voice-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.voice-info {
  text-align: center;
}

.voice-info h4 {
  margin: 0 0 5px 0;
  color: #1e3c72;
}

.voice-info p {
  margin: 0 0 10px 0;
  color: #666;
  font-size: 14px;
}

.quality-indicator {
  display: flex;
  align-items: center;
  gap: 8px;
}

.quality-bar {
  flex: 1;
  height: 4px;
  background: #f0f0f0;
  border-radius: 2px;
  overflow: hidden;
}

.quality-fill {
  height: 100%;
  background: #28a745;
  transition: width 0.3s ease;
}

.recording-area {
  text-align: center;
  margin-bottom: 30px;
}

.recording-visual {
  margin-bottom: 20px;
}

.microphone-icon {
  font-size: 64px;
  color: #1e3c72;
  margin-bottom: 15px;
  transition: color 0.3s ease;
}

.microphone-icon.active {
  color: #dc3545;
}

.recording-status p {
  color: #666;
  margin: 0;
}

.recording-controls {
  display: flex;
  justify-content: center;
  gap: 15px;
}

.btn {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.2s ease;
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-record {
  background: #dc3545;
  color: white;
}

.btn-play {
  background: #28a745;
  color: white;
}

.btn-compare {
  background: #1e3c72;
  color: white;
}

.btn-primary {
  background: #1e3c72;
  color: white;
}

.btn-secondary {
  background: #6c757d;
  color: white;
}

.btn-sm {
  padding: 6px 12px;
  font-size: 12px;
}

.comparison-result {
  margin-top: 30px;
}

.comparison-result h3 {
  color: #1e3c72;
  margin-bottom: 20px;
}

.result-display {
  display: flex;
  align-items: center;
  gap: 30px;
  margin-bottom: 20px;
}

.score-circle {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: bold;
}

.score-circle.high {
  background: #28a745;
}

.score-circle.medium {
  background: #ffc107;
}

.score-circle.low {
  background: #dc3545;
}

.score-value {
  font-size: 24px;
  margin-bottom: 5px;
}

.score-label {
  font-size: 14px;
}

.result-info {
  flex: 1;
}

.info-item {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
}

.info-item label {
  min-width: 80px;
  color: #666;
}

.status.match {
  color: #28a745;
}

.status.possible {
  color: #ffc107;
}

.status.nomatch {
  color: #dc3545;
}

.result-actions {
  display: flex;
  gap: 15px;
}

.history-section {
  background: white;
  border-radius: 8px;
  padding: 25px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.history-section h2 {
  color: #1e3c72;
  margin-bottom: 20px;
}

.history-table table {
  width: 100%;
  border-collapse: collapse;
}

.history-table th {
  background: #f8f9fa;
  padding: 12px;
  text-align: left;
  font-weight: 600;
  color: #1e3c72;
  border-bottom: 1px solid #eee;
}

.history-table td {
  padding: 12px;
  border-bottom: 1px solid #eee;
}

.similarity-bar {
  display: flex;
  align-items: center;
  gap: 10px;
}

.similarity-fill {
  width: 80px;
  height: 8px;
  background: #28a745;
  border-radius: 4px;
}

.status-badge {
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 500;
}

.status-badge.match {
  background: #d4edda;
  color: #155724;
}

.status-badge.possible {
  background: #fff3cd;
  color: #856404;
}

.status-badge.nomatch {
  background: #f8d7da;
  color: #721c24;
}

@media (max-width: 768px) {
  .comparison-container {
    flex-direction: column;
  }
  
  .voice-grid {
    grid-template-columns: 1fr;
  }
  
  .result-display {
    flex-direction: column;
    text-align: center;
  }
  
  .recording-controls {
    flex-direction: column;
  }
}
</style> 